﻿using System;
using System.Collections;
using System.Xml;
using InfoJetSoft.Service.Entity;

namespace InfoJetSoft.Service.Util
{
	//实现一些个性化XML节点Clone的功能。
	class CloneUtil
	{
		//CID 0397 //2009.09.08 //Begin
		public static void copyChildren(XmlDocument targetDoc, XmlElement targetElement, XmlElement sourceElement )
		{
			DOMUtil.removeChildNodes( targetElement );
			foreach( XmlNode childNode in sourceElement.ChildNodes )
			{
				if( childNode is XmlElement )
				{
					XmlElement childElement = childNode as XmlElement;
					XmlElement clonedElement = CloneUtil.cloneElement( targetDoc, childElement );
					targetElement.AppendChild( clonedElement );
				}
				else if( childNode is XmlText )
				{
					XmlText childText = childNode as XmlText;
					XmlText clonedText = targetDoc.CreateTextNode( childText.Value );
					targetElement.AppendChild( clonedText );
				}
			}
		}
		//CID 0397 //2009.09.08 //End

		//将其它文档元素element，克隆到targetDoc。
		//类似与node.clone(true)后再targetDoc.importNode()。
		//首先因为历史原因，当时不知道有importNode()，所以自己写了。
		//而且有一些自定义功能，如xsi和PI的处理，所以没有改成importNode。
		public static XmlElement cloneElement(XmlDocument targetDoc, XmlElement element)
		{
			XmlElement newElement = targetDoc.CreateElement(element.Name,element.NamespaceURI);
			
			foreach (XmlAttribute attr in element.Attributes)
			{
				XmlAttribute newAttr = (XmlAttribute) targetDoc.CreateAttribute(attr.Name, attr.NamespaceURI);
				newAttr.Value = attr.Value;
				newElement.SetAttributeNode(newAttr);
				
				string prefix = attr.Prefix;
				if (prefix != null)
				{
					if( prefix.Equals( "xsi" ) )
					{
						XmlAttribute xsiAttr = (XmlAttribute) targetDoc.CreateAttribute("xmlns:xsi" , JetConstant.URI_XMLNS);
						xsiAttr.Value = JetConstant.URI_XSI;
						newElement.SetAttributeNode( xsiAttr ); 
					}
				}
			}
			
			bool hasElementChild = false;
			foreach (XmlNode node in element.ChildNodes)
			{
				if (node is XmlElement)
				{
					newElement.AppendChild(cloneElement( targetDoc, (XmlElement) node));
					hasElementChild = true;
				}
				//添加对XmlProcessingInstruction的克隆,在向Web Services提交整个Xml文档,其中包括PI时这个操作是必需的.
				if (node is XmlProcessingInstruction)
				{
					XmlProcessingInstruction pi = (XmlProcessingInstruction)node;
					XmlProcessingInstruction clonePi = targetDoc.CreateProcessingInstruction( pi.Target, pi.Data );
					newElement.AppendChild( clonePi );
				}
			}
			if( !hasElementChild ){
				foreach (XmlNode node in element.ChildNodes) {
					if (node is XmlText) {
						XmlText text = (XmlText) node;
						XmlText newText = (XmlText) targetDoc.CreateTextNode(text.Value);
						newElement.AppendChild(newText);
					}
				}
			}

			return newElement;
		}

		//将其它文档的元素element，克隆到targetDoc，同时修改element的prefix和namespace-uri。
		//用于DataObjectDBWorker中。
		public static XmlElement cloneNsElement(XmlDocument targetDoc, XmlElement element, string prefix, string ns ){
			XmlElement newElement = targetDoc.CreateElement( prefix, element.LocalName, ns );

			foreach (XmlAttribute attr in element.Attributes) {
				XmlAttribute newAttr = (XmlAttribute) targetDoc.CreateAttribute( attr.Name, attr.NamespaceURI );
				newAttr.Value = attr.Value;
				newElement.SetAttributeNode(newAttr);
			}

			bool hasElementChild = false;
			foreach (XmlNode node in element.ChildNodes) {
				if (node is XmlElement) {
					newElement.AppendChild(cloneNsElement( targetDoc, (XmlElement) node, prefix, ns));
					hasElementChild = true;
				}
			}
			if( !hasElementChild ){
				foreach (XmlNode node in element.ChildNodes) {
					if (node is XmlText) {
						XmlText text = (XmlText) node;
						XmlText newText = (XmlText) targetDoc.CreateTextNode(text.Value);
						newElement.AppendChild(newText);
					}
				}
			}

			return newElement;
		}
		
	}
}